<?php

/**
 * contact : 刘经理 19326416371
 * company : 版权所属 四川北星惯牌科技有限公司
 **/


namespace app\common\manager;

use app\common\constant\Constant;
use app\common\library\Wechat;
use app\common\model\Level;
use app\common\model\MoneyLog;
use app\common\model\PurchaseRecord;
use app\common\model\ScoreLog;
use app\common\model\User;
use app\common\model\UserAccount;
use think\Db;
use think\Exception;

class UserAccountManager extends BaseManager
{

    CONST TYPE_RECHARGE = 1;
    CONST TYPE_RECHARGE_MESSAGE = '充值';
    CONST TYPE_FREEZE = 2;
    CONST TYPE_FREEZE_MESSAGE = '冻结';
    CONST TYPE_WITHDRAWAL = 3;
    CONST TYPE_WITHDRAWAL_MESSAGE = '提现';
    CONST TYPE_TEAM = 4;
    CONST TYPE_TEAM_MESSAGE = '组队';
    CONST TYPE_MATCH = 5;
    CONST TYPE_MATCH_MESSAGE = '竞赛';
    CONST TYPE_VOUCHER= 6;
    CONST TYPE_VOUCHER_MESSAGE= '购买';
    CONST TYPE_FREEZE_RETURN = 7;
    CONST TYPE_FREEZE_RETURN_MESSAGE = '解冻';
    CONST TYPE_REFUND = 8;
    CONST TYPE_REFUND_MESSAGE = '组队退款';
    CONST TYPE_REWARD = 9;
    CONST TYPE_REWARD_MESSAGE = '邀请奖励';
    CONST TYPE_INVITED = 10;
    CONST TYPE_INVITED_MESSAGE = '被邀请奖励';

    CONST TYPE_MATCH_RETURN = 11;
    CONST TYPE_MATCH_RETURN_MESSAGE = '赛事退款';

    CONST TYPE_RECHARGE_REWARD = 12;
    CONST TYPE_RECHARGE_REWARD_MESSAGE = '充值奖励';

    CONST TYPE_PROXY_RECHARGE_REWARD = 13;
    CONST TYPE_PROXY_RECHARGE_REWARD_MESSAGE = '充值代理奖励';

    CONST TYPE_PROXY_STORE_TEAM_REWARD = 14;
    CONST TYPE_PROXY_STORE_TEAM_REWARD_MESSAGE = '门店组队代理返点';

    CONST TYPE_PROXY_CAPTAIN_TEAM_REWARD = 15;
    CONST TYPE_PROXY_CAPTAIN_TEAM_REWARD_MESSAGE = '队长组队代理返点';

    CONST TYPE_SYS_CHANGE = 16;
    CONST TYPE_SYS_CHANGE_MESSAGE = '系统变更';

    CONST TYPE_ASSISTANT_REWARD = 17;
    CONST TYPE_ASSISTANT_REWARD_MESSAGE = '助教分成';

    CONST TYPE_ASSISTANT_REFUND = 18;
    CONST TYPE_ASSISTANT_REFUND_MESSAGE = '助教退款';

   /* CONST TYPE_TEAM_REBATE = 11;
    CONST TYPE_TEAM_REBATE_MESSAGE = '组队返点';*/

    CONST TYPE_MONEY_ARRAY = [
        self::TYPE_RECHARGE => [
            'value' => self::TYPE_RECHARGE,
            'memo' => self::TYPE_RECHARGE_MESSAGE,
        ],

        self::TYPE_FREEZE => [
            'value' => self::TYPE_FREEZE,
            'memo' => self::TYPE_FREEZE_MESSAGE,
        ],

        self::TYPE_WITHDRAWAL => [
            'value' => self::TYPE_WITHDRAWAL,
            'memo' => self::TYPE_WITHDRAWAL_MESSAGE,
        ],

        self::TYPE_TEAM => [
            'value' => self::TYPE_TEAM,
            'memo' => self::TYPE_TEAM_MESSAGE,
        ],

        self::TYPE_MATCH => [
            'value' => self::TYPE_MATCH,
            'memo' => self::TYPE_MATCH_MESSAGE,
        ],

        self::TYPE_VOUCHER => [
            'value' => self::TYPE_VOUCHER,
            'memo' => self::TYPE_VOUCHER_MESSAGE,
        ],

        self::TYPE_FREEZE_RETURN => [
            'value' => self::TYPE_FREEZE_RETURN,
            'memo' => self::TYPE_FREEZE_RETURN_MESSAGE,
        ],

        self::TYPE_REFUND => [
            'value' => self::TYPE_REFUND,
            'memo' => self::TYPE_REFUND_MESSAGE,
        ],
        self::TYPE_REWARD => [
            'value' => self::TYPE_REWARD,
            'memo' => self::TYPE_REWARD_MESSAGE,
        ],
        self::TYPE_INVITED => [
            'value' => self::TYPE_INVITED,
            'memo' => self::TYPE_INVITED_MESSAGE,
        ],
        self::TYPE_MATCH_RETURN=>[
            'value' => self::TYPE_MATCH_RETURN,
            'memo' => self::TYPE_MATCH_RETURN_MESSAGE,
        ],
        self::TYPE_RECHARGE_REWARD=>[
            'value' => self::TYPE_RECHARGE_REWARD,
            'memo' => self::TYPE_RECHARGE_REWARD_MESSAGE,
        ],

        self::TYPE_PROXY_RECHARGE_REWARD=>[
            'value' => self::TYPE_PROXY_RECHARGE_REWARD,
            'memo' => self::TYPE_PROXY_RECHARGE_REWARD_MESSAGE,
        ],

        self::TYPE_PROXY_STORE_TEAM_REWARD=>[
            'value' => self::TYPE_PROXY_STORE_TEAM_REWARD,
            'memo' => self::TYPE_PROXY_STORE_TEAM_REWARD_MESSAGE,
        ],

        self::TYPE_PROXY_CAPTAIN_TEAM_REWARD=>[
            'value' => self::TYPE_PROXY_CAPTAIN_TEAM_REWARD,
            'memo' => self::TYPE_PROXY_CAPTAIN_TEAM_REWARD_MESSAGE,
        ],
        self::TYPE_SYS_CHANGE=>[
            'value' => self::TYPE_SYS_CHANGE,
            'memo' => self::TYPE_SYS_CHANGE_MESSAGE,
        ],

        self::TYPE_ASSISTANT_REWARD=>[
            'value' => self::TYPE_ASSISTANT_REWARD,
            'memo' => self::TYPE_ASSISTANT_REWARD_MESSAGE,
        ],

        self::TYPE_ASSISTANT_REFUND=>[
            'value' => self::TYPE_ASSISTANT_REFUND,
            'memo' => self::TYPE_ASSISTANT_REFUND_MESSAGE,
        ],

    ];



    CONST TYPE_SCORE_TEAM = 1;
    CONST TYPE_SCORE_TEAM_MESSAGE = '组队';
    CONST TYPE_SCORE_MATCH = 2;
    CONST TYPE_SCORE_MATCH_MESSAGE = '竞赛';
    CONST TYPE_SCORE_INVITE= 3;
    CONST TYPE_SCORE_INVITE_MESSAGE= '邀请';
    CONST TYPE_SCORE_INVITED= 4;
    CONST TYPE_SCORE_INVITED_MESSAGE= '被邀请';
    CONST TYPE_SCORE_SYS= 5;
    CONST TYPE_SCORE_SYS_MESSAGE= '系统';

    CONST TYPE_SCORE_ARRAY = [
        self::TYPE_SCORE_TEAM => [
            'value' => self::TYPE_SCORE_TEAM,
            'memo' => self::TYPE_SCORE_TEAM_MESSAGE,
        ],

        self::TYPE_SCORE_MATCH => [
            'value' => self::TYPE_SCORE_MATCH,
            'memo' => self::TYPE_SCORE_MATCH_MESSAGE,
        ],

        self::TYPE_SCORE_INVITE => [
            'value' => self::TYPE_SCORE_INVITE,
            'memo' => self::TYPE_SCORE_INVITE_MESSAGE,
        ],

        self::TYPE_SCORE_INVITED => [
            'value' => self::TYPE_SCORE_INVITED,
            'memo' => self::TYPE_SCORE_INVITED_MESSAGE,
        ],

        self::TYPE_SCORE_SYS => [
            'value' => self::TYPE_SCORE_SYS,
            'memo' => self::TYPE_SCORE_SYS_MESSAGE,
        ],
    ];


    CONST CHANGE_TYPE_MONEY = 1;
    CONST CHANGE_TYPE_SCORE = 2;

    CONST CHANGE_TYPE_PAYMENT=1;
    CONST CHANGE_TYPE_PAYMENT_MESSAGE='支出';
    CONST CHANGE_TYPE_INCOME = 2;
    CONST CHANGE_TYPE_INCOME_MESSAGE = '收入';

    CONST CHANGE_TYPE_ARRAY = [
        self::CHANGE_TYPE_PAYMENT=>[
            'value'=>self::CHANGE_TYPE_PAYMENT,
            'memo'=>self::CHANGE_TYPE_PAYMENT_MESSAGE,
        ],
        self::CHANGE_TYPE_INCOME=>[
            'value'=>self::CHANGE_TYPE_INCOME,
            'memo'=>self::CHANGE_TYPE_INCOME_MESSAGE,
        ]
    ];
    public static function getAccount($uid)
    {
        try {
            $userAccount = UserAccount::where('user_id',$uid)->find();
            unset($userAccount->id);
            unset($userAccount->user_id);
            unset($userAccount->status);
            return ['code'=>self::$successCode,'message'=>self::$successMessage,'data'=>$userAccount];
        }catch (Exception $exception){
            return ['code'=>self::$failCode,'message'=>$exception->getMessage()];
        }
    }
    /**
     * 通过用户id创建用户账户
     * @param int $userId
     * @param bool $trans
     * @return array
     */
    public static function account(int $userId,bool $trans=true):array
    {
        $userAccount = null;
        if ($trans)
            Db::startTrans();
        try {
            if (!UserAccount::where('user_id',$userId)->find()) {
                $userAccount = UserAccount::create([
                    'user_id'=>$userId
                ]);
            }
            $userAccount = UserAccount::where('user_id',$userId)->find();
            if ($trans)
                Db::commit();
            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
            self::setData($userAccount);
        }catch (Exception $exception){
            if ($trans)
                Db::rollback();
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }

        return ['code'=>self::getStatusCode(),'message'=>self::getMessage(),'data'=>self::getData()];
    }

    /**
     * 账户金额变动
     * @param int $userId  用户uid
     * @param float $money 金额
     * @param int $outIn 1=支出,2=收入
     * @param int $datetime 时间戳
     * @param int $detail 1=充值,2=冻结,3=提现,4=组队,5=竞赛,6=购买体验卡,7=解冻
     * @param array $extend [扩展字段]['relation_id'=>$relation_id,'relation_order'=>$relation_order]  relation_id 相关id  relation_order 相关订单号
     * @param boolean $trans 是否开启事务
     * @return array
     */
    public static function money(int $userId,float $money,int $outIn,int $datetime,int $detail,array $extend=[],bool $trans=true):array
    {
        //file_put_contents('recharge.txt','func:'.json_encode(func_get_args()),FILE_APPEND);
        $datetime = date('Y-m-d H:i:s',$datetime);
        $result = ['code'=>self::$failCode,'message'=>self::$failMessage];
        if ($trans)
            Db::startTrans();
        try {
            $userInfo = User::get($userId);
            $userAccount = UserAccount::where(['user_id'=>$userId])->find();
            if(!$userAccount){
                $accountResult = self::account($userId);
                if ($accountResult['code']==self::$failCode){
                    throw new Exception($accountResult['message']);
                }
                $userAccount = $accountResult['data'];
            }
            switch ($detail){
                case self::TYPE_RECHARGE:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                        'total' => Db::raw('total + '.$money),
                        'recharge' => Db::raw('recharge + '.$money),
                        'available_balance' => Db::raw('available_balance + '.$money),
                        'version' => Db::raw('version + 1'),
                    ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_RECHARGE_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_RECHARGE,$message,$extend,false);
                    break;
                case self::TYPE_FREEZE:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('total','>=',$money)
                        ->where('available_balance','>=',$money)
                        ->where('version',$userAccount->version)
                        ->update([
                        'available_balance' => Db::raw('available_balance - '.$money),
                        'freeze' => Db::raw('freeze + '.$money),
                        'version' => Db::raw('version + 1'),
                    ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_FREEZE_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,0,UserMoneyManager::TYPE_FREEZE,$message,$extend,false);
                    break;

                case self::TYPE_WITHDRAWAL:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('freeze','>=',$money)
                        ->where('total','>=',$money)
                        ->where('version',$userAccount->version)
                        ->update([
                        'total' => Db::raw('total - '.$money),
                        'freeze' => Db::raw('freeze - '.$money),
                        'withdrawal' => Db::raw('withdrawal + '.$money),
                        'version' => Db::raw('version + 1'),
                    ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_WITHDRAWAL_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,-$money,UserMoneyManager::TYPE_DECREASE,UserMoneyManager::TYPE_WITHDRAWAL,$message,$extend,false);
                    break;
                case self::TYPE_TEAM:
                    if ($outIn==self::CHANGE_TYPE_PAYMENT){
                        if(!UserAccount::where('user_id',$userId)
                            ->where('available_balance','>=',$money)
                            ->where('version',$userAccount->version)
                            ->update([
                            'total' => Db::raw('total - '.$money),
                            'available_balance' => Db::raw('available_balance - '.$money),
                            'version' => Db::raw('version + 1')
                        ])){
                            throw new Exception('账户余额变动失败');
                        }
                        $message = sprintf(UserMoneyManager::TYPE_DECREASE_TEAM_MESSAGE,$userInfo->username,$datetime,$money);
                        $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,-$money,UserMoneyManager::TYPE_DECREASE,UserMoneyManager::TYPE_TEAM,$message,$extend,false);
                    }else if ($outIn==self::CHANGE_TYPE_INCOME){
                        if(!UserAccount::where('user_id',$userId)
                            ->where('version',$userAccount->version)
                            ->update([
                                'total' => Db::raw('total + '.$money),
                                'available_balance' => Db::raw('available_balance + '.$money),
                                'income_sum' => Db::raw('income_sum + '.$money),
                                'version' => Db::raw('version + 1')
                            ]))
                        {
                            throw new Exception('账户余额变动失败');
                        }
                        $message = sprintf(UserMoneyManager::TYPE_INCREASE_TEAM_MESSAGE,$userInfo->username,$datetime,$money);
                        $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_TEAM,$message,$extend,false);
                    }

                    break;
                case self::TYPE_MATCH:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('available_balance','>=',$money)
                        ->where('total','>=',$money)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total - '.$money),
                            'available_balance' => Db::raw('available_balance - '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_MATCH_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,-$money,UserMoneyManager::TYPE_DECREASE,UserMoneyManager::TYPE_MATCH,$message,$extend,false);
                    break;

                case self::TYPE_VOUCHER:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('available_balance','>=',$money)
                        ->where('total','>=',$money)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total - '.$money),
                            'available_balance' => Db::raw('available_balance - '.$money),
                            'consumed_money' => Db::raw('consumed_money + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_VOUCHER_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,-$money,UserMoneyManager::TYPE_DECREASE,UserMoneyManager::TYPE_VOUCHER,$message,$extend,false);
                    break;

                case self::TYPE_FREEZE_RETURN:

                    if(!UserAccount::where('user_id',$userId)
                        ->where('freeze','>=',$money)
                        ->where('version',$userAccount->version)
                        ->update([
                            'freeze' => Db::raw('freeze - '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_UNFREEZE_RETURN_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,0,UserMoneyManager::TYPE_UNFREEZE_RETURN,$message,$extend,false);
                    break;

                case self::TYPE_REFUND:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_REFUND_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_REFUND,$message,$extend,false);
                    break;

                case self::TYPE_REWARD:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'income_sum' => Db::raw('income_sum + '.$money),
                            'version' => Db::raw('version + 1'),
                        ]))
                    {
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_REWARD_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_REWARD,$message,$extend,false);
                    break;

                case self::TYPE_INVITED:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'income_sum' => Db::raw('income_sum + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_INVITED_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_INVITED,$message,$extend,false);
                    break;

                case self::TYPE_MATCH_RETURN:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_MATCH_RETURN_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_MATCH_RETURN,$message,$extend,false);
                    break;

                case self::TYPE_RECHARGE_REWARD:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'income_sum' => Db::raw('income_sum + '.$money),
                            'version' => Db::raw('version + 1'),
                        ]))
                    {
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_RECHARGE_REWARD_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_RECHARGE_REWARD,$message,$extend,false);
                    break;

                case self::TYPE_PROXY_RECHARGE_REWARD:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'income_sum' => Db::raw('income_sum + '.$money),
                            'version' => Db::raw('version + 1'),
                        ]))
                    {
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_PROXY_RECHARGE_REWARD_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_PROXY_RECHARGE_REWARD,$message,$extend,false);
                    break;
                case self::TYPE_PROXY_STORE_TEAM_REWARD:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'income_sum' => Db::raw('income_sum + '.$money),
                            'version' => Db::raw('version + 1'),
                        ]))
                    {
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_PROXY_STORE_TEAM_REWARD_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_PROXY_STORE_TEAM_REWARD,$message,$extend,false);
                    break;

                case self::TYPE_PROXY_CAPTAIN_TEAM_REWARD:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'income_sum' => Db::raw('income_sum + '.$money),
                            'version' => Db::raw('version + 1'),
                        ]))
                    {
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_PROXY_CAPTAIN_TEAM_REWARD_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_PROXY_CAPTAIN_TEAM_REWARD,$message,$extend,false);
                    break;

                case self::TYPE_SYS_CHANGE:
                    if ($outIn==self::CHANGE_TYPE_PAYMENT){
                        if(!UserAccount::where('user_id',$userId)
                            ->where('available_balance','>=',$money)
                            ->where('version',$userAccount->version)
                            ->update([
                                'total' => Db::raw('total - '.$money),
                                'available_balance' => Db::raw('available_balance - '.$money),
                                'version' => Db::raw('version + 1')
                            ])){
                            throw new Exception('账户余额变动失败');
                        }
                        $message = sprintf(UserMoneyManager::TYPE_SYS_CHANGE_MESSAGE,$userInfo->username,$datetime,$money);
                        $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,-$money,UserMoneyManager::TYPE_DECREASE,UserMoneyManager::TYPE_SYS_CHANGE,$message,$extend,false);
                    }else if ($outIn==self::CHANGE_TYPE_INCOME){
                        if(!UserAccount::where('user_id',$userId)
                            ->where('version',$userAccount->version)
                            ->update([
                                'total' => Db::raw('total + '.$money),
                                'available_balance' => Db::raw('available_balance + '.$money),
                                'version' => Db::raw('version + 1')
                            ]))
                        {
                            throw new Exception('账户余额变动失败');
                        }
                        $message = sprintf(UserMoneyManager::TYPE_SYS_CHANGE_MESSAGE,$userInfo->username,$datetime,$money);
                        $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_SYS_CHANGE,$message,$extend,false);
                    }

                    break;
                case self::TYPE_ASSISTANT_REWARD:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'income_sum' => Db::raw('income_sum + '.$money),
                            'version' => Db::raw('version + 1'),
                        ]))
                    {
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_ASSISTANT_REWARD_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_ASSISTANT_REWARD,$message,$extend,false);
                    break;

                case self::TYPE_ASSISTANT_REFUND:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(UserMoneyManager::TYPE_ASSISTANT_REFUND_MESSAGE,$userInfo->username,$datetime,$money);
                    $result = UserMoneyManager::UserMoneyLog($userAccount,$userId,$money,UserMoneyManager::TYPE_INCREASE,UserMoneyManager::TYPE_ASSISTANT_REFUND,$message,$extend,false);
                    break;
                default:
                    break;


            }
            if ($result['code']==self::$failCode){
                throw new Exception($result['message']);
            }

            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
            if ($trans)
                Db::commit();
        }catch (Exception $exception){
            if ($trans)
                Db::rollback();
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage().$exception->getLine());
        }

        return ['code'=>self::getStatusCode(),'message'=>self::getMessage()];
    }


    /**
     * 积分余额变动
     * @param int $userId 用户id
     * @param float $score 积分数量 [必须大于 0 ]
     * @param int $outIn 1=支出,2=收入
     * @param int $datetime 时间戳
     * @param int $detail 1=组队,2=竞赛,3=拉新,4=被拉新
     * @param array $extend [扩展字段]['relation_id'=>$relation_id,'relation_order'=>$relation_order]  relation_id 相关id  relation_order 相关订单号
     * @param boolean $trans 是否开启事务
     * @return array
     */
    public static function score(int $userId,float $score,int $outIn,int $datetime,int $detail,array $extend=[],bool $trans=true):array
    {
        $result = ['code'=>self::$failCode,'message'=>self::$failMessage];
        if ($trans)
            Db::startTrans();
        try {
            $datetime = date('Y-m-d H:i:s',$datetime);
            $userInfo = User::get($userId);
            $userAccount = UserAccount::where('user_id',$userId)->find();
            if(!$userAccount){
                $accountResult = self::account($userId);
                if ($accountResult['code']==self::$failCode){
                    throw new Exception($accountResult['message']);
                }
                $userAccount = UserAccount::where('user_id',$userId)->find();
            }
            switch ($detail){
                case self::TYPE_SCORE_TEAM:
                    if($outIn == self::CHANGE_TYPE_INCOME){
                        if(!UserAccount::where('user_id',$userId)
                            ->where('version',$userAccount->version)
                            ->update([
                                'score' => Db::raw('score + '.$score),
                                'got_score' => Db::raw('got_score + '.$score),
                                'available_score' => Db::raw('available_score + '.$score),
                                'version' => Db::raw('version + 1'),
                            ])){
                            throw new Exception('账户积分变动失败');
                        }

                        $message = sprintf(UserScoreManager::TYPE_INCREASE_TEAM_MESSAGE,$userInfo->username,$datetime,$score);
                        $result = UserScoreManager::UserScoreLog($userAccount,$userId,$score,UserScoreManager::TYPE_TEAM,UserScoreManager::TYPE_INCREASE,$message,$extend,false);
                    }else if($outIn == self::CHANGE_TYPE_PAYMENT){
                        if(!UserAccount::where('user_id',$userId)
                            ->where('version',$userAccount->version)
                            ->update([
                                'score' => Db::raw('score - '.$score),
                                'available_score' => Db::raw('available_score - '.$score),
                                'version' => Db::raw('version + 1'),
                            ])){
                            throw new Exception('账户积分变动失败');
                        }

                        $message = sprintf(UserScoreManager::TYPE_DECREASE_TEAM_MESSAGE,$userInfo->username,$datetime,$score);
                        $result = UserScoreManager::UserScoreLog($userAccount,$userId,-$score,UserScoreManager::TYPE_TEAM,UserScoreManager::TYPE_DECREASE,$message,$extend,false);

                    }
                    break;

                case self::TYPE_SCORE_MATCH:
                    if($outIn == self::CHANGE_TYPE_INCOME) {
                        if(!UserAccount::where('user_id', $userId)
                            ->where('version', $userAccount->version)
                            ->update([
                            'available_score' => Db::raw('available_balance + ' . $score),
                            'score' => Db::raw('score + ' . $score),
                            'got_score' => Db::raw('got_score + ' . $score),
                            'version' => Db::raw('version + 1'),
                        ])){
                            throw new Exception('账户积分变动失败');
                        }

                        $message = sprintf(UserScoreManager::TYPE_INCREASE_MATCH_MESSAGE, $userInfo->username, $datetime, $score);
                        $result = UserScoreManager::UserScoreLog($userAccount, $userId, $score, UserScoreManager::TYPE_INCREASE, UserScoreManager::TYPE_MATCH, $message, $extend, false);
                    }else if ($outIn == self::CHANGE_TYPE_PAYMENT){
                        if(!UserAccount::where('user_id', $userId)
                            ->where('version', $userAccount->version)
                            ->where('available_score','>=', $score)
                            ->where('score','>=', $score)
                            ->update([
                            'available_score' => Db::raw('available_balance - ' . $score),
                            'score' => Db::raw('score - ' . $score),
                            'version' => Db::raw('version + 1'),
                        ])){
                            throw new Exception('账户积分变动失败');
                        }

                        $message = sprintf(UserScoreManager::TYPE_DECREASE_MATCH_MESSAGE, $userInfo->username, $datetime, $score);
                        $result  =UserScoreManager::UserScoreLog($userAccount, $userId, -$score, UserScoreManager::TYPE_DECREASE, UserScoreManager::TYPE_MATCH, $message, $extend, false);
                    }
                    break;

                case self::TYPE_SCORE_INVITE:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'score' => Db::raw('score + '.$score),
                            'available_score' => Db::raw('available_score + '.$score),
                            'got_score' => Db::raw('got_score + '.$score),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户积分变动失败');
                    }

                    $message = sprintf(UserScoreManager::TYPE_INCREASE_INVITE_INVITED_MESSAGE,$userInfo->username,$datetime,$score);
                    $result = UserScoreManager::UserScoreLog($userAccount,$userId,$score,UserScoreManager::TYPE_INVITE,UserScoreManager::TYPE_INCREASE,$message,$extend,false);
                    break;
                case self::TYPE_SCORE_INVITED:
                    if(!UserAccount::where('user_id',$userId)
                        ->where('version',$userAccount->version)
                        ->update([
                            'score' => Db::raw('score + '.$score),
                            'available_score' => Db::raw('available_score + '.$score),
                            'got_score' => Db::raw('got_score + '.$score),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户积分变动失败');
                    }

                    $message = sprintf(UserScoreManager::TYPE_INCREASE_INVITE_USER_MESSAGE,$userInfo->username,$datetime,$score);
                    $result = UserScoreManager::UserScoreLog($userAccount,$userId,$score,UserScoreManager::TYPE_INVITE,UserScoreManager::TYPE_INCREASE,$message,$extend,false);
                    break;
                case self::TYPE_SCORE_SYS:
                    if($outIn == self::CHANGE_TYPE_INCOME) {
                        if(!UserAccount::where('user_id', $userId)
                            ->where('version', $userAccount->version)
                            ->update([
                                'available_score' => Db::raw('available_balance + ' . $score),
                                'score' => Db::raw('score + ' . $score),
                                'got_score' => Db::raw('got_score + ' . $score),
                                'version' => Db::raw('version + 1'),
                            ])){
                            throw new Exception('账户积分变动失败');
                        }

                        $message = sprintf(UserScoreManager::TYPE_SYS_CHANGE_MESSAGE, $userInfo->username, $datetime, $score);
                        $result = UserScoreManager::UserScoreLog($userAccount, $userId, $score, UserScoreManager::TYPE_INCREASE, UserScoreManager::TYPE_SYS_CHANGE, $message, $extend, false);
                    }else if ($outIn == self::CHANGE_TYPE_PAYMENT){
                        if(!UserAccount::where('user_id', $userId)
                            ->where('version', $userAccount->version)
                            ->where('available_score','>=', $score)
                            ->where('score','>=', $score)
                            ->update([
                                'available_score' => Db::raw('available_balance - ' . $score),
                                'score' => Db::raw('score - ' . $score),
                                'version' => Db::raw('version + 1'),
                            ])){
                            throw new Exception('账户积分变动失败');
                        }

                        $message = sprintf(UserScoreManager::TYPE_SYS_CHANGE_MESSAGE, $userInfo->username, $datetime, $score);
                        $result  =UserScoreManager::UserScoreLog($userAccount, $userId, -$score, UserScoreManager::TYPE_DECREASE, UserScoreManager::TYPE_SYS_CHANGE, $message, $extend, false);
                    }
                    break;
                default:
                    break;
            }
            if ($result['code'] == self::$failCode){
                throw new Exception($result['message']);
            }
            if ($trans)
                Db::commit();
            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
        }catch (Exception $exception){
            if ($trans)
                Db::rollback();
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }
        return ['code'=>self::getStatusCode(),'message'=>self::getMessage()];
    }

    /**
     * 获取金额日志
     * @param int $userId
     * @param int $type
     * @param int $detail
     * @param array $where
     * @param int $page
     * @param int $step
     * @return array
     */
    public static function moneyLog(int $userId,int $type=0,int $detail=0,array $where = [],int $page=1,int $step=Constant::PAGE_LIMIT):array
    {
        $return = ['total'=>0,'totalPage'=>1,'currentPage'=>$page,'list'=>[]];
        try {
            $start = ($page-1)*$step;
            $total = MoneyLog::where('user_id',$userId)->where(function ($query) use ($type) {
                if ($type){
                    return $query->where('type',$type);
                }
            })->where(function ($query) use ($detail) {
                if ($detail){
                    return $query->where('detail',$detail);
                }
            })->where(function ($query) use ($where) {
                if ($where){
                    return $query->where($where);
                }
            })->count();

            $data  = MoneyLog::where('user_id',$userId)->where(function ($query) use ($type) {
               if ($type){
                   return $query->where('type',$type);
               }
            })->where(function ($query) use ($detail) {
                if ($detail){
                    return $query->where('detail',$detail);
                }
            })->where(function ($query) use ($where) {
                if ($where){
                    return $query->where($where);
                }
            })->limit($start,$step)->order('id desc')->select();

            if ($data){
                foreach ($data as $k=>&$v){
                    $v['type_name'] = self::CHANGE_TYPE_ARRAY[$v['type']]['memo'] ?? '不详';
                    $v['detail_name'] = self::TYPE_MONEY_ARRAY[$v['detail']]['memo'] ?? '不详';
                }
            }
            $page = page($total,$step,$page);
            $return['list'] = $data;
            $return = array_merge($return,$page);
        }catch (Exception $exception){
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }
        return ['code'=>self::getStatusCode(),'message'=>self::getMessage(),'data'=>$return];
    }



    /**
     * 获取积分日志
     * @param int $userId
     * @param int $type
     * @param int $detail
     * @param array $where
     * @param int $page
     * @param int $step
     * @return array
     */
    public static function scoreLog(int $userId,int $type=0,int $detail=0,array $where = [],int $page=1,int $step=Constant::PAGE_LIMIT):array
    {
        $return = ['total'=>0,'totalPage'=>1,'currentPage'=>$page,'list'=>[]];
        try {
            $start = ($page-1)*$step;
            $total = ScoreLog::where('user_id',$userId)->where(function ($query) use ($type) {
                if ($type){
                    return $query->where('type',$type);
                }
            })->where(function ($query) use ($detail) {
                if ($detail){
                    return $query->where('detail',$detail);
                }
            })->where(function ($query) use ($where) {
                if ($where){
                    return $query->where($where);
                }
            })->count();

            $data  = ScoreLog::where('user_id',$userId)->where(function ($query) use ($type) {
                if ($type){
                    return $query->where('type',$type);
                }
            })->where(function ($query) use ($detail) {
                if ($detail){
                    return $query->where('detail',$detail);
                }
            })->where(function ($query) use ($where) {
                if ($where){
                    return $query->where($where);
                }
            })->limit($start,$step)->select();

            if ($data){
                foreach ($data as $k=>&$v){
                    $v['type_name'] = self::CHANGE_TYPE_ARRAY[$v['type']]['memo'] ?? '不详';
                    $v['detail_name'] = self::TYPE_SCORE_ARRAY[$v['detail']]['memo'] ?? '不详';
                }
            }
            $page = page($total,$step,$page);
            $return['list'] = $data;
            $return = array_merge($return,$page);
        }catch (Exception $exception){
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }
        return ['code'=>self::getStatusCode(),'message'=>self::getMessage(),'data'=>$return];
    }

    public static function getUserOpenId(User $user,$code)
    {

        try {
            $wechatInfo = Wechat::getUser($code);
            if (!empty($wechatInfo['openid'])){
                User::where('id',$user->id)->update(['open_id'=>$wechatInfo['openid']]);
            }
            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
        }catch (Exception $exception){
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }
        return ['code'=>self::getStatusCode(),'message'=>self::getMessage()];
    }

    /**
     * 用戶等級升級
     * @param int $userId
     * @param string $type upgrade downgrade
     * @param bool $trans
     * @return array
     */
    public static function LevelUpgrade(int $userId,string $type='upgrade',bool $trans=true)
    {
        if ($trans)
            Db::startTrans();
        try {
            $userInfo = User::where('id',$userId)->find();
            $currentLevel = $userInfo['level'];
            $userAccount = UserAccount::where('user_id',$userId)->find();
            if ($type == 'upgrade'){
                $currentCount = bcadd($userAccount['join_count'],1);
            }else if ($type=='downgrade'){
                $currentCount = bcsub($userAccount['join_count'],1);
            }
            if ($type=='upgrade'){
                $currentLevelInfo = Level::where('all_count','<=',$currentCount)->order('all_count desc')->find();
            }else if ($type=='downgrade'){
                $currentLevelInfo = Level::where('all_count','<=',$currentCount)->order('all_count desc')->find();
            }

            if (isset($currentLevelInfo['vl_id']) && $currentLevelInfo['vl_id'] != $currentLevel){
                User::where('id',$userId)->update(['level'=>$currentLevelInfo['vl_id'],'updatetime'=>time()]);
            }

            if ($trans)
                Db::commit();
            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
        }catch (Exception $exception){
            if ($trans)
                Db::rollback();
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage().$exception->getLine());
        }

        return ['code'=>self::getStatusCode(),'message'=>self::getMessage()];
    }

    /**
     * @return array
     */
    public static function PurchaseRecord($userId,$page=1,$step=Constant::PAGE_LIMIT): array
    {
        $return = ['total'=>0,'totalPage'=>1,'currentPage'=>$page,'list'=>[]];
        try {
            $PurchaseRecordModel = new PurchaseRecord();
            $start = ($page-1)*$step;
            $total = $PurchaseRecordModel->alias('pr')
                ->join('goods g','g.g_id=pr.goods_id','inner')
                ->join('product p','g.pdu_id=p.pdu_id','left')
                ->where('pr.user_id',$userId)
                ->where('pr.status',PurchaseRecord::STATUS_SUCCESS)
                ->count();

            $data  = $PurchaseRecordModel->alias('pr')
                ->join('goods g','g.g_id=pr.goods_id','inner')
                ->join('product p','g.pdu_id=p.pdu_id','left')
                ->where('pr.user_id',$userId)
                ->where('pr.status',PurchaseRecord::STATUS_SUCCESS)
                ->field('pr.order,pr.amount,pr.goods_id,pr.is_balance,pr.goods_detail,pr.create_time,p.name,p.cover_image,p.thumbnail')
                ->limit($start,$step)->select();

            if ($data){
                foreach ($data as $k=>&$v){
                    if ($v->cover_image && strrpos($v->cover_image,'https')===false){
                        $v->cover_image = cdnurl($v->cover_image);
                    }

                    if ($v->thumbnail && strrpos($v->thumbnail,'https')===false){
                        $v->thumbnail = cdnurl($v->thumbnail);
                    }

                    if ($v->goods_detail){
                        $goods_detail = unserialize($v->goods_detail);
                        $v->validity_period = $goods_detail['validity_period'];
                    }else{
                        $v->validity_period = 0;
                    }
                }
            }
            $page = page($total,$step,$page);
            $return['list'] = $data;
            $return = array_merge($return,$page);
        }catch (Exception $exception){
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }
        return ['code'=>self::getStatusCode(),'message'=>self::getMessage(),'data'=>$return];
    }
}